package com.wpen.unit.service.job.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import com.wpen.unit.service.job.TaskExecLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wpen.unit.AppVariables;
import com.wpen.unit.cvt.job.JobExec1LogCvt;
import com.wpen.unit.cvt.job.TaskExecLogCvt;
import com.wpen.unit.cvt.job.TaskExecRedologCvt;
import com.wpen.unit.enums.DependType;
import com.wpen.unit.enums.ExecStatus;
import com.wpen.unit.infra.mybatis.job.po.DependonPo;
import com.wpen.unit.infra.mybatis.job.po.JobExec1LogPo;
import com.wpen.unit.infra.mybatis.job.po.TaskExecLogPo;
import com.wpen.unit.infra.mybatis.job.po.TaskExecRedologPo;
import com.wpen.unit.infra.repository.job.DependonRepository;
import com.wpen.unit.infra.repository.job.JobExec1LogRepository;
import com.wpen.unit.infra.repository.job.TaskExecLogRepository;
import com.wpen.unit.infra.repository.job.TaskExecRedologRepository;
import com.wpen.unit.utils.DateUtil;
import com.wpen.unit.web.dto.job.BatchAllLogListRequest;
import com.wpen.unit.web.dto.job.StatRequest;
import com.wpen.unit.web.dto.job.StatResponse;
import com.wpen.unit.web.dto.job.TaskExecLogListRequest;
import com.wpen.unit.web.dto.job.TaskExecLogListResponse;
import com.wpen.unit.web.dto.job.TaskExecLogListRowJobsResponse;
import com.wpen.unit.web.dto.job.TaskExecLogListRowsResponse;
import com.wpen.unit.web.dto.job.TaskExecRedologListRequest;
import com.wpen.unit.web.dto.job.TaskExecRedologListResponse;
import com.wpen.unit.web.dto.job.TaskExecRedologListRowsResponse;

/**
 * 任务执行日志业务处理.
 * 
 * @author Wang Peng
 * @date 2022-12-12
 */
@Service
public class TaskExecLogServiceImpl implements TaskExecLogService {

    @Autowired
    private DependonRepository dependonRepository;
    @Autowired
    private TaskExecLogRepository taskExecLogRepository;
    @Autowired
    private JobExec1LogRepository jobExec1LogRepository;
    @Autowired
    private TaskExecRedologRepository taskExecRedologRepository;

	@Override
	public StatResponse statTodayTaskExec(StatRequest statRequest) {
		StatResponse statResponse = new StatResponse();
		// 数据库查询
		TaskExecLogPo taskExecLogPo = new TaskExecLogPo();
		taskExecLogPo.setExecDate(DateUtil.format(DateUtil.FORMAT_DATE2));
		long total = taskExecLogRepository.count(taskExecLogPo);
		statResponse.setCount(total);
		taskExecLogPo.setExecDate(DateUtil.offset(Calendar.DAY_OF_YEAR, -1, DateUtil.FORMAT_DATE2));
		long total2 = taskExecLogRepository.count(taskExecLogPo);
		statResponse.setAlive(total2);
		return statResponse;
	}
    
    @Override
    public TaskExecLogListResponse queryListTaskExecLog(TaskExecLogListRequest taskExecLogListRequest) {
        int index = taskExecLogListRequest.getIndex();
        int size = taskExecLogListRequest.getSize();
        // 数据库查询
        TaskExecLogPo taskExecLogPo = TaskExecLogCvt.INSTANCE.queryListDto2Do(taskExecLogListRequest);

        List<TaskExecLogPo> taskExecLogPoLists = taskExecLogRepository.queryList(index, size, taskExecLogPo);

        // 返回响应信息
        TaskExecLogListResponse taskExecLogListResponse = new TaskExecLogListResponse();
        taskExecLogListResponse.setCount(0);
        if (taskExecLogPoLists != null) {
            // 查询任务作业
            JobExec1LogPo jobExec1LogWhere = new JobExec1LogPo();
            jobExec1LogWhere.setBatchExecLogId(taskExecLogPo.getBatchExecLogId());
            jobExec1LogWhere.setBatchTriggerTime(taskExecLogPo.getBatchTriggerTime());
            List<JobExec1LogPo> jobExec1LogPoLists = jobExec1LogRepository.queryList(index, size, jobExec1LogWhere);
            Map<Long, List<JobExec1LogPo>> mapJobExecLogs = new HashMap<>();
            if (jobExec1LogPoLists != null && !jobExec1LogPoLists.isEmpty()) {
                for (JobExec1LogPo jobExec1LogPo : jobExec1LogPoLists) {
                    if (mapJobExecLogs.containsKey(jobExec1LogPo.getTaskExecLogId())) {
                        mapJobExecLogs.get(jobExec1LogPo.getTaskExecLogId()).add(jobExec1LogPo);
                    } else {
                        List<JobExec1LogPo> groupByTask = new ArrayList<>();
                        groupByTask.add(jobExec1LogPo);
                        mapJobExecLogs.put(jobExec1LogPo.getTaskExecLogId(), groupByTask);
                    }
                }
            }
            taskExecLogListResponse.setCount(taskExecLogPoLists.size());
            List<TaskExecLogListRowsResponse> listRows = taskExecLogListResponse.getRows();
            for (TaskExecLogPo inTaskExecLogPo : taskExecLogPoLists) {
                TaskExecLogListRowsResponse row = TaskExecLogCvt.INSTANCE.queryListRowDo2Dto(inTaskExecLogPo);
                if (mapJobExecLogs.containsKey(inTaskExecLogPo.getId())) {
                    List<JobExec1LogPo> inJobExec1LogPos = mapJobExecLogs.get(inTaskExecLogPo.getId());
                    List<TaskExecLogListRowJobsResponse> childrens = row.getChildren();
                    int no = 0;
                    for (JobExec1LogPo inExec1LogPo : inJobExec1LogPos) {
                        no++;
                        TaskExecLogListRowJobsResponse children = JobExec1LogCvt.INSTANCE
                                .queryListForTaskDo2Dto(inExec1LogPo);
                        children.setTaskCode("Job." + no);
//                        if (inExec1LogPo.getJobCode().startsWith(inExec1LogPo.getTaskCode())) {
//                            children.setTaskCode(inExec1LogPo.getJobCode().substring(inExec1LogPo.getTaskCode().length()));
//                        }else {
//                            children.setTaskCode(inExec1LogPo.getJobCode());
//                        }
                        childrens.add(children);
                    }
                    row.setChildren(childrens);
                }
                listRows.add(row);
            }
            taskExecLogListResponse.setRows(listRows);
        }
        return taskExecLogListResponse;
    }

    @Override
    public TaskExecLogListResponse queryListBatchAllExecLog(BatchAllLogListRequest taskExecLogListRequest) {
        String biz = taskExecLogListRequest.getBizCode();
        String batch = taskExecLogListRequest.getBatchCode();

        Long batchLogId = taskExecLogListRequest.getBatchExecLogId();
        Long batchTriggerTime = taskExecLogListRequest.getBatchTriggerTime();
        List<TaskExecLogPo> taskExecLogPoLists = taskExecLogRepository.queryListByBatchId(batchLogId, batchTriggerTime);

        if (taskExecLogPoLists == null || taskExecLogPoLists.isEmpty()) {
            return new TaskExecLogListResponse();
        }

        // 查询当前batch下依赖的所有task
        List<DependonPo> dependonPos = dependonRepository.queryAllSubByParent(biz, batch, null, false);
        Map<String, DependonPo> nodeDos = new HashMap<>();
        Map<String, Integer> levelNums = new LinkedHashMap<>();
        Map<String, List<DependonPo>> parent2Childs = new HashMap<>();
        for (DependonPo dependonPo : dependonPos) {
            String oneKey = dependonPo.getBizCode() + "|" + dependonPo.getBatchCode() + "|" + dependonPo.getTaskCode()
                    + "|" + dependonPo.getJobCode();
            nodeDos.put(oneKey, dependonPo);

            String parentKey = dependonPo.getDpdonBizCode() + "|" + dependonPo.getDpdonBatchCode() + "|"
                    + dependonPo.getDpdonTaskCode() + "|" + dependonPo.getDpdonJobCode();
            if (parent2Childs.containsKey(parentKey)) {
                List<DependonPo> listParentChild = parent2Childs.get(parentKey);
                listParentChild.add(dependonPo);
            } else {
                List<DependonPo> listParentChild = new ArrayList<>();
                listParentChild.add(dependonPo);
                parent2Childs.put(parentKey, listParentChild);
            }
        }
        // 递归排层
        DependonPo root = new DependonPo();
        root.setBizCode(biz);
        root.setBatchCode(batch);
        root.setTaskCode(AppVariables.DEPENDON_PHD);
        root.setJobCode(AppVariables.DEPENDON_PHD);
        loopCheckLevel(root, parent2Childs, levelNums, 1);

        Map<Integer, List<String>> ordersMap = new HashMap<>();
        for (Map.Entry<String, Integer> entry : levelNums.entrySet()) {
            String key = entry.getKey();
            Integer val = entry.getValue(); // 排完的序号
            if (ordersMap.containsKey(val)) {
                ordersMap.get(val).add(key);
            } else {
                List<String> list = new ArrayList<>();
                list.add(key);
                ordersMap.put(val, list);
            }
        }
        // 排序序号
        Set<Integer> orderSet = ordersMap.keySet();
        TreeSet<Integer> treeSet = new TreeSet<>(((o1, o2) -> o1.compareTo(o2)));
        treeSet.addAll(orderSet);
        //
        Map<String, TaskExecLogPo> taskLogMaps = new HashMap<>();
        Map<String, Integer> taskSubNums = new HashMap<>();
        for (TaskExecLogPo taskLogPo : taskExecLogPoLists) {
            String oneKey = taskLogPo.getBizCode() + "|" + taskLogPo.getBatchCode() + "|" + taskLogPo.getTaskCode()
                    + "|" + AppVariables.DEPENDON_PHD;
            if (taskLogMaps.containsKey(oneKey)) {
                if (ExecStatus.comp(taskLogMaps.get(oneKey).getExecStatus(), taskLogPo.getExecStatus())) {
                    taskLogMaps.put(oneKey, taskLogPo);
                }
                taskSubNums.put(oneKey, taskSubNums.get(oneKey) + 1);
            } else {
                taskLogMaps.put(oneKey, taskLogPo);
                taskSubNums.put(oneKey, 1);
            }
        }

        // 查询任务作业
        List<JobExec1LogPo> jobExec1LogPoLists = jobExec1LogRepository.queryListByBatchId(batchLogId, batchTriggerTime);
        Map<String, List<JobExec1LogPo>> mapJobExecLogs = new HashMap<>();
        Map<String, Integer> taskSubJobs = new HashMap<>();
        if (jobExec1LogPoLists != null && !jobExec1LogPoLists.isEmpty()) {
            for (JobExec1LogPo jobExec1LogPo : jobExec1LogPoLists) {
                String oneKey = jobExec1LogPo.getBizCode() + "|" + jobExec1LogPo.getBatchCode() + "|" + jobExec1LogPo.getTaskCode()
                + "|" + AppVariables.DEPENDON_PHD;
                if (mapJobExecLogs.containsKey(oneKey)) {
                    mapJobExecLogs.get(oneKey).add(jobExec1LogPo);
                    taskSubJobs.put(oneKey, taskSubJobs.get(oneKey) + 1);
                } else {
                    List<JobExec1LogPo> groupByTask = new ArrayList<>();
                    groupByTask.add(jobExec1LogPo);
                    mapJobExecLogs.put(oneKey, groupByTask);
                    taskSubJobs.put(oneKey, 1);
                }
            }
        }
        TaskExecLogListResponse taskExecLogListResponse = new TaskExecLogListResponse();
        List<TaskExecLogListRowsResponse> listRows = taskExecLogListResponse.getRows();
        for (Integer order : orderSet) {
            List<String> keys = ordersMap.get(order);
            for (String oneDpd : keys) {
                TaskExecLogPo inTaskExecLogPo = taskLogMaps.get(oneDpd);
                Integer subNum = taskSubNums.get(oneDpd);
                Integer subJob = taskSubJobs.get(oneDpd);

                TaskExecLogListRowsResponse row =  TaskExecLogCvt.INSTANCE.queryListRowDo2Dto(inTaskExecLogPo);
                if(inTaskExecLogPo == null ) {
                	DependonPo dpdPo = nodeDos.get(oneDpd);
                	// 还没有执行
                	row = new TaskExecLogListRowsResponse();
                	row.setBizCode(dpdPo.getBizCode());
                	row.setBatchCode(dpdPo.getBatchCode());
                	row.setTaskCode(dpdPo.getTaskCode());
                	row.setBatchExecLogId(batchLogId);
                	row.setBatchTriggerTime(batchTriggerTime);
                	row.setExecStatus(ExecStatus.Wait.value());
                    row.setExecTime("--");
                }else {
                    row.setExecTime(DateUtil.execTime(inTaskExecLogPo.getStartupTime(), inTaskExecLogPo.getEndTime()));
                }
                row.setType(DependType.Task.value());
                if (mapJobExecLogs.containsKey(oneDpd)) {
                    List<JobExec1LogPo> inJobExec1LogPos = mapJobExecLogs.get(oneDpd);
                    List<TaskExecLogListRowJobsResponse> childrens = row.getChildren();
                    int no = 0;
                    for (JobExec1LogPo inExec1LogPo : inJobExec1LogPos) {
                        no++;
                        TaskExecLogListRowJobsResponse children = JobExec1LogCvt.INSTANCE
                                .queryListForTaskDo2Dto(inExec1LogPo);
                        //children.setTaskCode("Job." + inExec1LogPo.getDbCode() + "." + no);
                        children.setTaskCode(no + "."+ inExec1LogPo.getJobCode());
                        children.setType(DependType.Job.value());
                        children.setExecTime(DateUtil.execTime(inExec1LogPo.getStartupTime(), inExec1LogPo.getEndTime()));
                        childrens.add(children);
                    }
                    row.setChildren(childrens);
                }
                listRows.add(row);
            }
        }
        taskExecLogListResponse.setRows(listRows);
        return taskExecLogListResponse;
    }

    public void loopCheckLevel(DependonPo dependonPo, Map<String, List<DependonPo>> parent2Childs,
            Map<String, Integer> levelNums, int level) {
        String parentKey = dependonPo.getBizCode() + "|" + dependonPo.getBatchCode() + "|" + dependonPo.getTaskCode()
                + "|" + dependonPo.getJobCode();
        List<DependonPo> listSub = parent2Childs.get(parentKey);
        if (listSub != null && !listSub.isEmpty()) {
            for (DependonPo dependonPo2 : listSub) {
                String oneKey = dependonPo2.getBizCode() + "|" + dependonPo2.getBatchCode() + "|"
                        + dependonPo2.getTaskCode() + "|" + dependonPo2.getJobCode();
                levelNums.put(oneKey, level + 1);
            }
            for (DependonPo dependonPo2 : listSub) {
                loopCheckLevel(dependonPo2, parent2Childs, levelNums, level + 1);
            }
        }
    }
    

    @Override
    public TaskExecRedologListResponse queryListTaskExecRedolog(TaskExecRedologListRequest taskExecRedologListRequest){
        int index = taskExecRedologListRequest.getIndex();
    	int size = taskExecRedologListRequest.getSize();
        // 数据库查询
        TaskExecRedologPo taskExecRedologPo = TaskExecRedologCvt.INSTANCE.queryListDto2Do(taskExecRedologListRequest);

        List<TaskExecRedologPo> taskExecRedologPoLists = taskExecRedologRepository.queryList(index, size,taskExecRedologPo);

        // 返回响应信息
        TaskExecRedologListResponse taskExecRedologListResponse = new TaskExecRedologListResponse();
        taskExecRedologListResponse.setTotal(0);
		taskExecRedologListResponse.setCount(0);
        if (taskExecRedologPoLists != null) {
            taskExecRedologListResponse.setTotal(taskExecRedologPoLists.size());
            taskExecRedologListResponse.setCount(taskExecRedologPoLists.size());
            List<TaskExecRedologListRowsResponse> listRows = taskExecRedologListResponse.getRows();
            for (TaskExecRedologPo inTaskExecRedologPo : taskExecRedologPoLists) {
                TaskExecRedologListRowsResponse row = TaskExecRedologCvt.INSTANCE.queryListRowDo2Dto(inTaskExecRedologPo);
                listRows.add(row);
            }
            taskExecRedologListResponse.setRows(listRows);
        }
        return taskExecRedologListResponse;
    }

}
